﻿
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Threading.Tasks;

using Kalman;
using Newtonsoft.Json.Linq;

namespace QuDao
{
    /// <summary>
    /// 数据表sys_role_authorize关联的业务对象，处理该表相关的业务逻辑
    /// </summary>
    public sealed partial class RoleAuthorizeBO : SingletonBase<RoleAuthorizeBO>
    {
        readonly IFreeSql fsql;
        public RoleAuthorizeBO() : base()
        {
            fsql = ServiceLocator.Instance.GetRequiredService<IFreeSql>();
        }

        #region Generate Code

        /// <summary>
        /// 获取角色权限
        /// </summary>
        /// <param name="id">主键ID的值</param>
        /// <returns></returns>
        public T GetItem<T>(int id)
        {
            var item = fsql.Select<RoleAuthorize>().Where(a => a.ID == id).ToOne<T>();
            return item;
        }

        /// <summary>
        /// 获取角色权限数据列表
        /// </summary>
        /// <returns></returns>
        public List<T> GetList<T>(int[] ids)
        {
            var list = fsql.Select<RoleAuthorize>().Where(a => ids.Contains(a.ID)).ToList<T>();
            return list;
        }

        /// <summary>
        /// 新增角色权限
        /// </summary>
        public int Add(RoleAuthorize entity)
        {
            entity.CreateTime = DateTime.Now;
            entity.ModifyTime = DateTime.Now;
            entity.ID = (int)fsql.Insert(entity).ExecuteIdentity();
            return entity.ID;
        }

        /// <summary>
        /// 修改角色权限
        /// </summary>
        public int Modify(RoleAuthorize dto)
        {
            var item = GetItem<RoleAuthorize>(dto.ID) ?? throw new AppException($"角色权限不存在：{dto.ID}");
            var update = fsql.Update<RoleAuthorize>(dto.ID).Set(a => a.ModifyTime, DateTime.Now);
            if (dto.ID != item.ID) update.Set(a => a.ID, dto.ID);
            if (dto.RoleID != item.RoleID) update.Set(a => a.RoleID, dto.RoleID);
            if (dto.MenuID != item.MenuID) update.Set(a => a.MenuID, dto.MenuID);

            return update.ExecuteAffrows();
        }

        /// <summary>
        /// 删除角色权限数据
        /// </summary>
        /// <returns>返回影响行数</returns>
        public int Delete(int[] ids)
        {
            return fsql.Delete<RoleAuthorize>().Where(a => ids.Contains(a.ID)).ExecuteAffrows();
        }

        /// <summary>
        /// 删除角色权限数据
        /// </summary>
        /// <returns>返回影响行数</returns>
        public int Delete(int id)
        {
            var ids = new int[] { id };
            return Delete(ids);
        }

        /// <summary>
        /// 后台查询数据（分页）
        /// </summary>
        /// <param name="req">分页查询请求对象</param>
        public PagingResult<T> Query<T>(PagingRequest req)
        {
            var select = fsql.Select<RoleAuthorize>();
            foreach (var item in req.FilterItems)
            {
                switch (item.Field)
                {
                    //case "RoleAuthorizeID":
                    //    select.Where(a => a.RoleAuthorizeID == int.Parse(item.Value));
                    //    break;
                    //case "RoleAuthorizeName":
                    //    select.Where(a => a.RoleAuthorizeName.Contains(item.Value));
                    //    break;
                    default:
                        break;
                }
            }

            if (!string.IsNullOrEmpty(req.SortExp))
            {
                select.OrderBy(req.SortExp);//自定义排序
            }
            else
            {
                select.OrderByDescending(a => a.ID);//默认排序
            }

            var sql = select.ToSql();

            var list = select.Count(out var total).Page(req.PageIndex, req.PageSize).ToList<T>();
            return new PagingResult<T>
            {
                PageIndex = req.PageIndex,
                PageSize = req.PageSize,
                Data = list,
                Total = (int)total
            };
        }

        #endregion

        /// <summary>
        /// 获取角色拥有的权限列表
        /// </summary>
        /// <returns></returns>
        public List<RoleAuthorize> GetListByRole(int roleID)
        {
            var list = fsql.Select<RoleAuthorize>().Where(a => a.RoleID == roleID).ToList();
            return list;
        }

        ///// <summary>
        ///// 获取指定角色的授权菜单数据列表
        ///// </summary>
        //public IEnumerable<AuthorizeMenuDto> GetListByRoleID(int roleID)
        //{
        //    var role = RoleBO.Instance.GetItem<Role>(roleID);
        //    if (role == null) throw new AppException($"角色不存在：{roleID}");

        //    var dic = MenuBO.Instance.GetDic();
        //    var list = fsql.Select<RoleAuthorize>().Where(a => a.RoleID == roleID).ToList();
        //    var authorizeList = new List<AuthorizeMenuDto>();

        //    foreach (var item in list)
        //    {
        //        if (!dic.ContainsKey(item.MenuID)) continue;

        //        var menu = dic[item.MenuID];
        //        authorizeList.Add(new AuthorizeMenuDto
        //        {
        //            MenuID = item.MenuID,
        //            MenuName = menu.MenuName,
        //            TID = menu.TID,
        //            ParentID = menu.ParentID,
        //            Icon = menu.Icon,
        //            SortFlag = menu.SortFlag,
        //            Url = menu.Url,
        //            ButtonList = item.ButtonList,
        //            IsEnable = menu.IsEnable
        //        });
        //    }

        //    return authorizeList;
        //}

        /// <summary>
        /// 新增或更新角色授权数据（为角色授权）
        /// </summary>
        /// <param name="roleID"></param>
        /// <param name="list"></param>
        /// <returns></returns>
        public void AddOrUpdate(int roleID, int menuType, int[] menuIDs)
        {
            var role = RoleBO.Instance.GetItem<Role>(roleID) ?? throw new AppException($"角色不存在：{roleID}");
            var menuDic = MenuBO.Instance.GetDic(menuType);
            var dic = new Dictionary<int, AuthorizeDto>();

            //由于子菜单的部分选择不会返回上级菜单ID，这里要做下处理
            foreach (var id in menuIDs)
            {
                if (dic.ContainsKey(id)) continue;
                if (!menuDic.ContainsKey(id)) continue;

                var menu = menuDic[id];
                dic.Add(id, new AuthorizeDto { MenuID = id });

                if (menu.ParentID == 0) continue; //已经是顶层菜单
                if (dic.ContainsKey(menu.ParentID)) continue; //上级菜单已加入

                dic.Add(menu.ParentID, new AuthorizeDto { MenuID = menu.ParentID }); //加入上级菜单权限（注意：这里只支持两级菜单，两级以上继续判断）
            }

            var list = dic.Values.ToList();
            var oldList = fsql.Select<RoleAuthorize>().Where(a => a.RoleID == roleID).ToList();
            var addList = new List<RoleAuthorize>();
            var modifyList = new List<AuthorizeDto>();
            var deleteIDs = new List<int>();

            //处理新增和修改的数据
            foreach (var item in list)
            {
                var oldItem = oldList.Where(p => p.MenuID == item.MenuID).SingleOrDefault();

                if (oldItem == null)
                {
                    addList.Add(new RoleAuthorize
                    {
                        RoleID = roleID,
                        MenuID = item.MenuID,
                        CreateTime = DateTime.Now,
                        ModifyTime = DateTime.Now
                    });
                }
                else
                {
                    //if (oldItem.ButtonList != item.ButtonList)
                    //{
                    //    modifyList.Add(item);
                    //}
                }
            }

            //处理删除的数据
            foreach (var item in oldList)
            {
                var newItem = list.Where(p => p.MenuID == item.MenuID).SingleOrDefault();
                if (newItem == null)
                {
                    deleteIDs.Add(item.ID);
                }
            }

            if (addList.Any()) fsql.Insert(addList).ExecuteAffrows();
            //if (modifyList.Any()) fsql.Update<RoleAuthorize>().SetSource(modifyList, null).UpdateColumns(new string[] { "ButtonList" }).ExecuteAffrows();
            if (deleteIDs.Any()) fsql.Delete<RoleAuthorize>().Where(a => deleteIDs.Contains(a.ID)).ExecuteAffrows();
        }

    }
}
